package com.games.portal.processor;


import java.util.ArrayList;
import java.util.List;

import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;

import com.games.portal.db.GamesDatabase;
import com.games.portal.db.GamesProvider;
import com.games.portal.model.Game;
import com.games.portal.model.GamesContainer;
import com.games.portal.rest.GameConstants;
import com.games.portal.rest.Method;
import com.games.portal.rest.RestMethod;
import com.games.portal.rest.RestMethodFactory;
import com.games.portal.rest.RestMethodResult;

/**
 * Executes the actual GET and processes the JSON response and saves it on the SQLite DB
 * @author hirsche
 *
 */
public class GameProcessor {

	private Context context;

	public GameProcessor(Context context) {
		this.context = context;
	}
	
	/**
	 * Execute, process and update
	 * @param callback
	 */
	public void getGameList(GameProcessorCallback callback) {
		// (4) Insert-Update the ContentProvider with a status column and
		// results column
		// Look at ContentProvider example, and build a content provider
		// that tracks the necessary data.

		// (5) Call the REST method
		// Create a RESTMethod class that knows how to assemble the URL,
		// and performs the HTTP operation.

		@SuppressWarnings("unchecked")
		RestMethod<GamesContainer> getGameMethod = RestMethodFactory.getInstance().getRestMethod(
				GameConstants.CONTENT_URI, Method.GET, null, null);
		RestMethodResult<GamesContainer> result = getGameMethod.execute();

		/*
		 * (8) Insert-Update the ContentProvider status, and insert the result
		 * on success Parsing the JSON response (on success) and inserting into
		 * the content provider
		 */

		updateContentProvider(result);

		// (9) Operation complete callback to Service

		callback.send(result.getStatusCode());

	}

	/**
	 * update SQLite
	 * @param result
	 */
	private void updateContentProvider(RestMethodResult<GamesContainer> result) {
		
		//nothing to update, request failed
		if (result == null || result.getStatusCode() != 200) {
			return;
		}
		
		ArrayList<ContentProviderOperation> opsInsert = 
				new ArrayList<ContentProviderOperation>();
		ArrayList<ContentProviderOperation> opsUpdate = 
				new ArrayList<ContentProviderOperation>();
		
		GamesContainer resource = result.getResource();
		List<Game> gameList = resource.getGameList();
		context.getContentResolver().delete(GamesProvider.CONTENT_URI,
				null, null);
		for (Game game: gameList) {
			Cursor cursor = null;
			try {
				cursor = context.getContentResolver().query(GamesProvider.CONTENT_URI,
						null,GamesDatabase.COL_NAME + "= ? and "+GamesDatabase.COL_URL+ " =  ?" , new String[]{game.getName(),game.getUrl()}, null);
				if (cursor.moveToFirst()) {
					String[] selectionArgs = new String[]{cursor.getString(cursor.getColumnIndexOrThrow
							(GamesDatabase.ID))};
					String selection = GamesDatabase.ID + "= ?"; 
					opsUpdate.add(
							ContentProviderOperation.newUpdate(GamesProvider.CONTENT_URI)
							.withSelection(selection, selectionArgs)
							.withValue(GamesDatabase.COL_URL,game.getUrl())
							.withValue(GamesDatabase.COL_IMAGE_URL, game.getImage_url())
							.withValue(GamesDatabase.COL_NAME, game.getName())
							.withValue(GamesDatabase.COL_CATEGORY_NAME, game.getCategoryName())
							.withYieldAllowed(true)
							.build());
				} else {
					opsInsert.add(
							ContentProviderOperation.newInsert(GamesProvider.CONTENT_URI)
							.withValue(GamesDatabase.COL_URL,game.getUrl())
							.withValue(GamesDatabase.COL_IMAGE_URL, game.getImage_url())
							.withValue(GamesDatabase.COL_NAME, game.getName())
							.withValue(GamesDatabase.COL_CATEGORY_NAME, game.getCategoryName())
							.withYieldAllowed(true)
							.build());
				}
			} finally {
				if (cursor != null) {
					cursor.close();
				}
			}
		}
			try {
				if (!opsInsert.isEmpty())
					context.getContentResolver().
					applyBatch(GamesProvider.AUTHORITY, opsInsert);
				if (!opsUpdate.isEmpty())
					context.getContentResolver().
					applyBatch(GamesProvider.AUTHORITY, opsUpdate);
			} catch (RemoteException e) {
				// do s.th.
			} catch (OperationApplicationException e) {
				// do s.th.
			}

		
	}
}
